import { useCallback, useEffect, useRef } from "react";
import { Message, StompSubscription } from "@stomp/stompjs";
import {
  WebSocketChatSessionHeartBeatMessage,
  WebSocketChatSessionHeartBeatMessageDTO,
} from "@/types/stomp";
import ChatDetailPageStore from "@/store/chat-detail-page";
import { useChatDetailPageState } from "@/hooks/chat/chat-detail-page";
import { useStompClient } from "@/hooks/stomp/stomp-service";

type TypingStatusOptions = {
  onTypingStart?: () => void;
  onTypingEnd?: () => void;
  sessionId?: string; // 会话ID
  typingDelay?: number; // 输入脱离毫秒
};

type TypingSetStatus = {
  sessionId: string; // 会话ID
  typing: boolean; // 是否正在打字
};

// 心跳订阅频道
const HEARTBEAT_SUBSCRIBE_CHANNEL = "/user/topic/heartbeat";
//心跳发送目的地
const HEARTBEAT_DESTINATION = "/app/heartbeat";
// 默认心跳间隔(ms)
const DEFAULT_HEARTBEAT_INTERVAL = 3000;

/**
 * 用于管理打字状态的自定义 Hook
 * 获取打字状态不需要参数，记录打字状态需要参数
 * @param options 可选项：打字开始/结束回调、延迟
 */
export function useTypingStatus(
  options: TypingStatusOptions = {}
): [
  receiverTyping: boolean,
  setTypingStatus: (params: TypingSetStatus) => void
] {
  const { client, connected } = useStompClient();
  const { receiverTyping } = useChatDetailPageState();
  const { sessionId, onTypingStart, onTypingEnd, typingDelay = 5000 } = options;
  const heartbeatIntervalRef = useRef<NodeJS.Timeout | null>(null);

  // 打字状态函数 - 在组件内部定义
  const setTypingStatus = useCallback(
    (params: TypingSetStatus) => {
      if (!client || !connected) return;

      const { sessionId, typing } = params;

      // 发送心跳消息，判断用户的输入状态和是否正在看着该会话
      const heartbeat: WebSocketChatSessionHeartBeatMessageDTO = {
        sessionId,
        typing,
      };
      client.publish({
        destination: HEARTBEAT_DESTINATION,
        body: JSON.stringify(heartbeat),
      });

      // 如果正在输入，启动定时发送心跳
      if (typing && !heartbeatIntervalRef.current) {
        heartbeatIntervalRef.current = setInterval(() => {
          if (connected) {
            client.publish({
              destination: HEARTBEAT_DESTINATION,
              body: JSON.stringify(heartbeat),
            });
          }
        }, DEFAULT_HEARTBEAT_INTERVAL);
      } else if (!typing && heartbeatIntervalRef.current) {
        // 如果停止输入，清除定时器
        clearInterval(heartbeatIntervalRef.current);
        heartbeatIntervalRef.current = null;
      }
    },
    [client, connected]
  );

  // 如果有会话ID，则进行订阅
  useEffect(() => {
    if (!sessionId || !client || !connected) return;

    const timerRef = useRef<NodeJS.Timeout | null>(null);
    const { setReceiverTyping } = ChatDetailPageStore.getState().actions;
    let subscription: StompSubscription | null = null;

    // 订阅心跳频道
    subscription = client.subscribe(
      HEARTBEAT_SUBSCRIBE_CHANNEL,
      (message: Message) => {
        const heartbeatMsg = JSON.parse(
          message.body
        ) as WebSocketChatSessionHeartBeatMessage;
        if (heartbeatMsg.typing) {
          onTypingStart && onTypingStart();
          setReceiverTyping(heartbeatMsg.typing);

          // 清除之前的定时器
          if (timerRef.current) {
            clearTimeout(timerRef.current);
          }

          // 设置超时后将状态重置
          timerRef.current = setTimeout(() => {
            setReceiverTyping(false);
            onTypingEnd && onTypingEnd();
          }, typingDelay);
        }
      },
      { sessionId }
    );

    // 清理函数
    return () => {
      // 清理订阅
      if (subscription) {
        subscription.unsubscribe();
      }
      // 清理定时器
      if (timerRef.current) {
        clearTimeout(timerRef.current);
      }
      // 清理心跳定时器
      if (heartbeatIntervalRef.current) {
        clearInterval(heartbeatIntervalRef.current);
        heartbeatIntervalRef.current = null;
      }
    };
  }, [sessionId, client, connected, typingDelay, onTypingStart, onTypingEnd]);

  // 组件卸载时清理
  useEffect(() => {
    return () => {
      if (heartbeatIntervalRef.current) {
        clearInterval(heartbeatIntervalRef.current);
        heartbeatIntervalRef.current = null;
      }
    };
  }, []);

  return [receiverTyping, setTypingStatus];
}
